#include "nfc_hal_config.h"
#include <stdio.h>
#include "bit_define.h"
#define	TP_FWT_302us	2048
#define TP_dFWT	      192
uint8_t EMV_TEST = 0;
uint8_t EMV_DEBUG_LOG = 1;
extern uint8_t reg_cache_digital_index_array[8];
extern uint8_t reg_cache_digital[0x40];

extern void Config_RegConfig(hal_nfc_regval_t *config, uint8_t size);

/*
	page_sel:是否需要更新页码
*/
int hal_nfc_set_register(uint8_t page, uint8_t addr, uint8_t value, uint8_t page_sel)
{
    //__disable_irq();
    PFIC_DisableAllIRQ();

    if(page_sel)//需要重新选择页码
    {
        switch(page)
        {
        case 0:
        case 1:
        case 2:
        case 3:
            hal_nfc_write_register(0x37, 0);
            break;
        case 4:
            hal_nfc_write_register(0x37, 0x5e);
            break;
        case 5:
            hal_nfc_write_register(0x37, 0xae);
            break;
        case 6:
            hal_nfc_write_register(0x37, 0x5a);
            break;
        case 7:
            hal_nfc_write_register(0x37, 0xa5);
            break;
        case 8:
            hal_nfc_write_register(0x37, 0x55);
            break;
        case 9:
            hal_nfc_write_register(0x37, 0x95);
            break;
        case 10:
            hal_nfc_write_register(0x37, 0x3e);
            break;
        default:
            break;
        }
    }
    //写功能寄存器
    hal_nfc_write_register(addr, value);

   // __enable_irq();
    PFIC_EnableAllIRQ();
    return 0;
}

uint8_t hal_nfc_get_register(uint8_t page, uint8_t addr, uint8_t page_sel)
{
    //__disable_irq();
    PFIC_DisableAllIRQ();
    uint8_t reg;

    if(page_sel)//需要重新选择页码
    {
        switch(page)
        {
        case 0:
        case 1:
        case 2:
        case 3:
            hal_nfc_write_register(0x37, 0);
            break;
        case 4:
            hal_nfc_write_register(0x37, 0x5e);
            break;
        case 5:
            hal_nfc_write_register(0x37, 0xae);
            break;
        case 6:
            hal_nfc_write_register(0x37, 0x5a);
            break;
        case 7:
            hal_nfc_write_register(0x37, 0xa5);
            break;
        case 8:
            hal_nfc_write_register(0x37, 0x55);
            break;
        case 9:
            hal_nfc_write_register(0x37, 0x95);
            break;
        case 10:
            hal_nfc_write_register(0x37, 0x3e);
            break;
        default:
            break;
        }
    }
    //读功能寄存器
    reg = hal_nfc_read_register(addr);

    //__enable_irq();
    PFIC_EnableAllIRQ();
    return reg;
}

void hal_nfc_bit_set(uint8_t page, uint8_t addr, uint8_t value, uint8_t page_sel)
{
    hal_nfc_set_register(page, addr, hal_nfc_get_register(page, addr, page_sel) | value, 1);
}

void hal_nfc_bit_clear(uint8_t page, uint8_t addr, uint8_t value, uint8_t page_sel)
{
    hal_nfc_set_register(page, addr, hal_nfc_get_register(page, addr, page_sel) & ~value, 1);
}

uint8_t hal_nfc_bit_check(uint8_t page, uint8_t addr, uint8_t check_bit, uint8_t page_sel)
{
    uint8_t reg = hal_nfc_get_register(page, addr, page_sel);
    return ((reg & check_bit) == check_bit);
}

typedef struct RegList {
    hal_nfc_regval_t RegTable[200]; //数据域
    uint8_t index;                  //指针域

} RegList;

RegList RL;

void RegTable_Init()
{
    RL.index=0;
    memset(RL.RegTable,0,sizeof(hal_nfc_regval_t)*64);
    printf("RegTable Cleared\r\n");
}

void Push_RegConfig(hal_nfc_regval_t regconfig)
{
    RL.RegTable[RL.index].addr=regconfig.addr;
    RL.RegTable[RL.index].page=regconfig.page;
    RL.RegTable[RL.index].value=regconfig.value;
    RL.index++;
}

void Config_RegConfig(hal_nfc_regval_t *config, uint8_t size)
{
    uint8_t i;
    uint8_t has = 0;
    for(i=0; i<=RL.index; i++)
    {
#if 1
        for(int k = 0; k < size; k++)
        {
            has = 0;
            if((config+k)->page == RL.RegTable[i].page && ((config+k)->addr == RL.RegTable[i].addr))
            {
                (config + k)->value = RL.RegTable[i].value;
                has = 1;
                break;
            }
        }
        if(has == 0)
#endif
            hal_nfc_set_register(RL.RegTable[i].page,RL.RegTable[i].addr,RL.RegTable[i].value,1);
    }

}

int hal_nfc_config(hal_nfc_regval_t *config, uint8_t size)
{
    int i = 0;
    //	hal_nfc_pcd_reset();

    if(EMV_TEST)
    {
        //disable emd
        hal_nfc_bit_clear(1, 0x18, 1, 0);
        hal_nfc_set_register(10, 0x3f, 0x80, 1);
    }
    else
    {
        hal_nfc_antenna_off();
        drv_interface.hw_msleep(7);
    }
    if(EMV_TEST)
    {
        Config_RegConfig(config, size);
    }
    hal_nfc_set_register((config+i)->page, (config+i)->addr, (config+i)->value, 1);
    if(size>1)
    {
        for(i = 0; i < size; i++)
        {
            hal_nfc_set_register((config+i)->page, (config+i)->addr, (config+i)->value, ((config+i)->page != (config+i-1)->page));
        }
    }

    if(EMV_TEST==0)
    {
        hal_nfc_antenna_on();
        drv_interface.hw_msleep(7);
    }


    return HAL_STATUS_OK;
}



uint32_t htonl(uint32_t lval)
{
    return (((lval >> 24)&0x000000ff) + ((lval >> 8) & 0x0000ff00) + ((lval << 8) & 0x00ff0000) + ((lval << 24) & 0xff000000));
}

uint32_t ntohl(uint32_t lval)
{
    return (((lval >> 24)&0x000000ff) + ((lval >> 8) & 0x0000ff00) + ((lval << 8) & 0x00ff0000) + ((lval << 24) & 0xff000000));
}

void pcd_set_tmo(uint8_t fwi)
{
    uint32_t tmp;

    if(EMV_TEST)
    {
        //FDT = FWT + dFWT
        hal_nfc_write_register(REG_TPRESCALER, (TP_FWT_302us/* + TP_dFWT*/) & 0xFF);
        hal_nfc_write_register(REG_TMODE, BIT(7) | (((TP_FWT_302us/* + TP_dFWT*/)>>8) & 0xFF));
        if (fwi > 14)
        {
            fwi = 4;
        }

        tmp = g_pcd_module_info.uc_wtxm * (1 << fwi);


        if (tmp > (1 << 14))
        {   //FDTA,PICC,EXT <= (FWT+dFWT)Max //EMV CL 10.2.2.3 10.2.2.7
            tmp = (1 << 14);
        }
        tmp += (25+12); //25+12 = (FC_dTPCD + FC_dFWT)/4096; //TA204 ±¾À´¾Í²»Ó¦¸ÃÍ¨¹ý//20211203_EMV3.1ÐÂÔö"+20"£¬²Å¿ÉÍ¨¹ýTA412¼°Ò»ÏµÁÐcase
        hal_nfc_write_register(REG_TRELOADL, tmp	& 0xFF);
        hal_nfc_write_register(REG_TRELOADH, (tmp  & 0xFF00) >> 8);
    }
    else
    {
        tmp = 1 * (1 << fwi);

        hal_nfc_write_register(REG_TPRESCALER, (TP_FWT_302us) & 0xFF);
        hal_nfc_write_register(REG_TMODE, BIT(7) | (((TP_FWT_302us)>>8) & 0xFF));

        hal_nfc_write_register(REG_TRELOADL, tmp  & 0xFF);
        hal_nfc_write_register(REG_TRELOADH, (tmp & 0xFF00) >> 8);

    }


}

/*
 * @brief pcd_set_rate
 * 设置非接通信速率（A/B/F）
 *
 * @param
 *      rate: 速率
 *              '1'= 106kbps
 *              '2'= 212kbps
 *              '4'= 424kbps
 *              '8'= 848kbps
 *      type: 协议类型（A/B/F）
 *
 * @return: None
 */
void pcd_set_rate(uint8_t rate, uint8_t type)
{
    uint8_t val,rxwait;
    switch(rate)
    {
    case '1':
        hal_nfc_clear_register_bit(REG_TXMODE, BIT(4) | BIT(5) | BIT(6));
        hal_nfc_clear_register_bit(REG_RXMODE, BIT(4) | BIT(5) | BIT(6));
        hal_nfc_write_register(REG_MODWIDTH, 0x26);//Miller Pulse Length

        hal_nfc_write_register(REG_RXSEL, 0x88);

        break;

    case '2':
        hal_nfc_clear_register_bit(REG_TXMODE, BIT(4) | BIT(5) | BIT(6));
        hal_nfc_set_register_bit(REG_TXMODE, BIT(4));
        hal_nfc_clear_register_bit(REG_RXMODE, BIT(4) | BIT(5) | BIT(6));
        hal_nfc_set_register_bit(REG_RXMODE, BIT(4));
        hal_nfc_write_register(REG_MODWIDTH, 0x12);//Miller Pulse Length
        //rxwait相对于106基本速率需要增加相应倍数
        val = hal_nfc_read_register(REG_RXSEL);
        rxwait = ((val & 0x3F)*2);
        if (rxwait > 0x3F)
        {
            rxwait = 0x3F;
        }
        hal_nfc_write_register(REG_RXSEL,(rxwait | (val & 0xC0)));
        if(type == 'F')
        {
            hal_nfc_write_register(REG_RXSEL, 0x98);
            hal_nfc_write_register(REG_MODWIDTH, 0x15);
        }
        break;

    case '4':
        hal_nfc_clear_register_bit(REG_TXMODE, BIT(4) | BIT(5) | BIT(6));
        hal_nfc_set_register_bit(REG_TXMODE, BIT(5));
        hal_nfc_clear_register_bit(REG_RXMODE, BIT(4) | BIT(5) | BIT(6));
        hal_nfc_set_register_bit(REG_RXMODE, BIT(5));
        hal_nfc_write_register(REG_MODWIDTH, 0x0A);//Miller Pulse Length
        //rxwait相对于106基本速率需要增加相应倍数
        val = hal_nfc_read_register(REG_RXSEL);
        rxwait = ((val & 0x3F)*4);
        if (rxwait > 0x3F)
        {
            rxwait = 0x3F;
        }
        hal_nfc_write_register(REG_RXSEL,(rxwait | (val & 0xC0)));
        if(type == 'B')
        {
            hal_nfc_write_register(0x37, 0xAE);
            hal_nfc_write_register(0x32, 0x6D);
            hal_nfc_write_register(0x37, 0x00);
        }
        else if(type == 'F')		//ZZQ20220304-->F此处仅配置了速率，CRC及felica使能请在初始化进行配置
        {
            hal_nfc_write_register(REG_RXSEL, 0x98);
            hal_nfc_write_register(REG_MODWIDTH, 0x0A);
        }
        break;
    case '8':
        hal_nfc_clear_register_bit(REG_TXMODE, BIT(4) | BIT(5) | BIT(6));
        hal_nfc_set_register_bit(REG_TXMODE, BIT(4) | BIT(5));
        hal_nfc_clear_register_bit(REG_RXMODE, BIT(4) | BIT(5) | BIT(6));
        hal_nfc_set_register_bit(REG_RXMODE, BIT(4) | BIT(5));
        if(type == 'B')
        {
            hal_nfc_write_register(0x37, 0xAE);
            hal_nfc_write_register(0x32, 0x6D);
            hal_nfc_write_register(0x37, 0x00);
        }
        hal_nfc_write_register(REG_MODWIDTH, 0x04);//Miller Pulse Length
        //rxwait相对于106基本速率需要增加相应倍数
        val = hal_nfc_read_register(REG_RXSEL);
        rxwait = ((val & 0x3F)*8);
        if (rxwait > 0x3F)
        {
            rxwait = 0x3F;
        }
        hal_nfc_write_register(REG_RXSEL,(rxwait | (val & 0xC0)));

        break;


    default:
        hal_nfc_clear_register_bit(REG_TXMODE, BIT(4) | BIT(5) | BIT(6));
        hal_nfc_clear_register_bit(REG_RXMODE, BIT(4) | BIT(5) | BIT(6));
        hal_nfc_write_register(REG_MODWIDTH, 0x26);//Miller Pulse Length

        break;
    }
}

void pcd_delay_sfgi(uint8_t sfgi)
{
    //SFGT = (SFGT+dSFGT) = [(256 x 16/fc) x 2^SFGI] + [384/fc x 2^SFGI]
    //dSFGT =  384 x 2^FWI / fc
    hal_nfc_write_register(REG_TPRESCALER, (TP_FWT_302us + TP_dFWT) & 0xFF);
    hal_nfc_write_register(REG_TMODE, BIT(7) | (((TP_FWT_302us + TP_dFWT)>>8) & 0xFF));

    if (sfgi > 14 || sfgi < 1)
    {   //FDTA,PCD,MIN = 6078 * 1 / fc
        sfgi = 1;
    }

    hal_nfc_write_register(REG_TRELOADL, (1 << sfgi) & 0xFF);
    hal_nfc_write_register(REG_TRELOADH, ((1 << sfgi) >> 8) & 0xFF);

    hal_nfc_write_register(REG_COMIRQ, 0x7F);//清除中断
    hal_nfc_write_register(REG_COMIEN, BIT(0));
    hal_nfc_clear_register_bit(REG_TMODE,BIT(7));// clear TAuto
    hal_nfc_set_register_bit(REG_CONTROL,BIT(6));// set TStartNow

    while(!INT_PIN);// wait new INT
    //hal_nfc_set_register_bit(TModeReg,BIT(7));// recover TAuto
    pcd_set_tmo(g_pcd_module_info.ui_fwi); //recover timeout set
}


void pcd_set_tmo_FWT_n9(void)
{
    //(n x 128 + 84) / fc           ,   n = 9 ,  9*128+84=1236 clock  < 92 us, dN9 = 0.4 us = 5.4 clock
    //这个设置有点小，暂且以0.604 us作为FWT£，也可改为302us试一下
    // (0.302 ms) FWI=0
    hal_nfc_write_register(REG_TPRESCALER, 0x7F); // T=18.80 us
    hal_nfc_write_register(REG_TMODE,0x80);
    hal_nfc_write_register(REG_TRELOADL,0x0F);//  18.80 * (Reload + 1)
    hal_nfc_write_register(REG_TRELOADH,0);
}

void pcd_set_tmo_FWT_ACTVITION(void)
{
    uint32_t tmp;
    // 4096
    hal_nfc_write_register(REG_TPRESCALER, (TP_FWT_302us/* + TP_dFWT*/) & 0xFF);
    hal_nfc_write_register(REG_TMODE, BIT(7) | (((TP_FWT_302us/* + TP_dFWT*/)>>8) & 0xFF));
    tmp = 42;//(71680 + FC_dTPCD)/4096 =  17.5 + 25; //FWTACTIVATION + ¦¤TPCD

    hal_nfc_write_register(REG_TRELOADL, tmp	& 0xFF);
    hal_nfc_write_register(REG_TRELOADH, (tmp  & 0xFF00) >> 8);
}

void pcd_set_tmo_FWT_ATQB(void)
{
    uint32_t tmp;
    // 4096
    hal_nfc_write_register(REG_TPRESCALER, (TP_FWT_302us/* + TP_dFWT*/) & 0xFF);
    hal_nfc_write_register(REG_TMODE, BIT(7) | (((TP_FWT_302us/* + TP_dFWT*/)>>8) & 0xFF));
    /* tmp = 27 太长了，所以在FWT-ATQB中FC_dTPCD不能太长 */
    tmp = 2;//(7680 + FC_dTPCD)/4096 =  1.875 + 25; //FWTACTIVATION + ΔTPCD
    tmp = 4;// 针对NVC_V15 需要增加这个时间
    hal_nfc_write_register(REG_TRELOADL, tmp	& 0xFF);
    hal_nfc_write_register(REG_TRELOADH, (tmp  & 0xFF00) >> 8);
}
